/**
 * Copyright (C) 2007-2011 JUG Events Team <info@jugevents.org>
 *
 * This file is part of JUG Events - Core.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jugevents.core.po;

import java.io.Serializable;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Transient;

import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.search.annotations.DocumentId;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.Store;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.URL;
import org.jugevents.core.util.TextFilterUtils;

/**
 * Represents information about the speaker of the event.
 * @author Enrico Giurin
 *
 */
@Entity
@Indexed
@NamedQueries(value = {
    @NamedQuery(name = "Speaker.findEventsByPartialSpeakerEmail", query =
    "select e from Event e, Speaker s  where s.event=e and upper(s.email) like upper(?)"),
    @NamedQuery(name = "Speaker.allByEvent", query =
    "select s from Event e, Speaker s where s.event=e and e.id=?"),
    @NamedQuery(name = "Speaker.findSpeakersByPartialEventTitle", query =
    "select s from Event e, Speaker s where s.event=e  and upper(e.title) like upper(?)")})
    /* TODO V3: is it working?
@FullTextFilterDefs({
    @FullTextFilterDef(name = "onlyMyJUG", impl =
    SpeakerFilterFactory.class)
})*/
public class Speaker implements org.lambico.po.hibernate.Entity, Serializable {

    private static final long serialVersionUID = 1L;
    private static final Logger logger =
    		LoggerFactory.getLogger(Speaker.class);
    protected Long id;
    private String firstName;
    private String lastName;
    private String email;
    private String url;
    private String skypeId;
    private byte[] picture;
    private String resume;
    private Event event;
    private String filter = "Textile";
    private Long indexSpeaker;

    @Transient
    public Long getIndexSpeaker() {
        return indexSpeaker;
    }

    public void setIndexSpeaker(Long indexSpeaker) {
        this.indexSpeaker = indexSpeaker;
    }

    @Transient
    public String getFilter() {
        return filter;
    }

    public void setFilter(String filter) {
        this.filter = filter;
    }

    /**
     * Get the entity id.
     * 
     * @return the entity id.
     */
    @Id
    @DocumentId
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    //set size to 1MB because BLOB of MySQL is not enough to store
    //binary data bigger than 64k
    @Lob
    @Basic(fetch = FetchType.LAZY)
    @Column(length = 1048576)
    public byte[] getPicture() {
        return picture;
    }

    public void setPicture(byte[] picture) {
        if ((picture == null) || (picture.length == 0)) {
            //TODO manage in a clean way when picture is null
            logger.debug("Trying to set null picture has failed");
            return;
        }
        this.picture = picture;
    }

    @Column(length = 4096)
    @Field(index = Index.TOKENIZED, store = Store.NO)
    @NotBlank
    public String getResume() {
        return resume;
    }

    public void setResume(String resume) {
        this.resume = resume;
    }

    public void setEvent(Event event) {
        this.event = event;
    }

    @ManyToOne(targetEntity=Event.class)
    public Event getEvent() {
        return event;
    }

    public String getSkypeId() {
        return skypeId;
    }

    public void setSkypeId(String skypeId) {
        this.skypeId = skypeId;
    }

    @NotBlank
    @Email
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @URL
    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    @Field(index = Index.TOKENIZED, store = Store.NO)
    @NotBlank
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @Field(index = Index.TOKENIZED, store = Store.NO)
    @NotBlank
    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Transient
    public String getFilteredPreview() {
        String filteredPreview =
        		TextFilterUtils.filterText(this.getResume(), this.getFilter(),
                false);
        return filteredPreview;
    }

    public Speaker copyOfInstance() {
        try {
            return (Speaker) BeanUtils.cloneBean(this);
        } catch (Exception e) {
            logger.error("Failing to get a copy of Speaker instance: " + this.toString(), e);
            return null;
        }
    }

    /**
     * Default implementation of the equals method.
     * It return true if the objects are of the same type and have
     * the same id.
     *
     * @param obj The object to compare with this
     * @return true if the objects are equals
     */
    @Override
    public boolean equals(final Object obj) {
        boolean result = false;
        if (obj != null) {
            String className = obj.getClass().getName();
            if (className.indexOf("$$EnhancerByCGLIB$$") > 0) {
                className = className.substring(0, className.indexOf("$$EnhancerByCGLIB$$"));
            }
            if (this.getClass().getName().equals(className)) {
                if (this.getId() != null && this.getId().equals(((Speaker) obj).getId())) {
                    result = true;
                }
            }
        }
        return result;
    }

    /**
     * Default implementation of the hashcode method for an Entity.
     * It return the hascode of the Id, if the Id is not null.
     * It return the hascode of the Object, if the Id is null.
     *
     * @return The hashcode of the entity instance.
     */
    @Override
    public int hashCode() {
        int result;
        if (this.getId() != null) {
            result = this.getId().hashCode();
        } else {
            result = super.hashCode();
        }
        return result;
    }

    @Override
    public String toString() {
        return this.getClass().getName() + "[id=" + this.id + "]";
    }

}
